﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AForge.Video.DirectShow;
using AForge.Controls;
using LogLib;
using System.IO.MemoryMappedFiles;
using System.Threading;
using System.IO;
using ComLib.ConfigService;
using MetroFramework;
using System.Drawing.Imaging;
using System.Media;
using System.Diagnostics;
using ComLib.ComType;
using NewCapturerDemo.Config;
using System.Reflection;
using System.Threading.Tasks;
using NewCapturerDemo.DSLR;
using EOSDigital.SDK;
using ColorMatrix = System.Drawing.Imaging.ColorMatrix;
using EOSDigital.API;
using PipeClient;

namespace NewCapturerDemo
{
    public partial class FormCapturerDSLR : Form
    {
        #region 专用于异步发送启动消息
        protected IntPtr ParentFormHandle = IntPtr.Zero;
        /// <summary>
        /// 指示是否已经通知主窗体加载完成
        /// </summary>
        protected bool _bNotified = false;
        public string AppName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
        #endregion

        private Pen penWhite = new Pen(Color.FromArgb(255, 255, 255), 3f);

        private Pen penRed = new Pen(Color.FromArgb(255, 0, 0), 3f);

        private Pen penBlue = new Pen(Color.FromArgb(65, 148, 232), 3f);

        private Pen penGreen = new Pen(Color.FromArgb(0, 255, 0), 3f);

        private Pen penGray = new Pen(Color.FromArgb(128, 128, 128), 3f);

        protected SoundPlayer _player = new SoundPlayer();

       // private VideoCaptureDevice _device = null;

        private Byte[] Data = null;

        public static long MemoryCapacity = 50000000;

        public long nReadDataLength = 0;

        private RotateFlipType _rotateLiveView = RotateFlipType.Rotate90FlipXY;

        /// <summary>
        /// 实时取景状态是不是处于打开状态
        /// </summary>
        private bool _isPlayerOn = false;
        public bool OnLiving
        {
            get { return _isPlayerOn; }
        }

        /// <summary>
        /// 指示在拍照后是否显示照片预览
        /// </summary>
        private bool _showTakenPhoto = false;
        public bool ShowTakenPhoto
        {
            get { return _showTakenPhoto; }
        }

        /// <summary>
        /// 显示拍照特效
        /// </summary>
        private bool _displayEffects = false;
        public bool DisplayEffects
        {
            get { return _displayEffects; }
        }

        private List<KeyValuePair<string, string>> listDevices = new List<KeyValuePair<string, string>>();
        private CanonDSLRCamera _camera = new CanonDSLRCamera();
        private CameraOption _option;

        /// <summary>
        /// 控制拍照窗口的句柄
        /// </summary>
        protected IntPtr ControllerHandle = IntPtr.Zero;

        private const string shareName = "AforgeNewVideoFrame";

        private const string mutexName = "MemoryMapMutex";

        /// <summary>
        /// 相机参数设置对话框
        /// </summary>
        private FormDSLRCameraSetting formConfig;
        private bool _drawZoomRect;
        private bool _drawFocusRect;
        public object VideoFrameLock = new object();
        private Bitmap _videoFrame;
        public object EvfDataSetLock = new object();
        private EvfDataSet _evfDataSet;

        public Bitmap VideoFrame
        {
            get
            {
                lock (this.VideoFrameLock)
                {
                    if (this._videoFrame == null)
                    {
                        return null;
                    }
                    return ComLib.ComFun.BitmapFunc.BmpClone(this._videoFrame);
                }
            }
            set
            {
                lock (this.VideoFrameLock)
                {
                    if (this._videoFrame != null)
                    {
                        this._videoFrame.Dispose();
                    }
                    if (value != null)
                    {
                        this._videoFrame = ComLib.ComFun.BitmapFunc.BmpClone(value);
                    }
                    else
                    {
                        this._videoFrame = null;
                    }
                }
            }
        }

        public EvfDataSet EvfDataSet
        {
            get
            {
                lock (this.EvfDataSetLock)
                {
                    return this._evfDataSet;
                }
            }
            set
            {
                lock (this.EvfDataSetLock)
                {
                    this._evfDataSet = value;
                }
            }
        }

        public FormCapturerDSLR(CameraOption option)
        {
            _option = option;
            InitializeComponent();
            InitCtrls();
        }

        public FormCapturerDSLR(CameraOption option,string arg)
        {
            _option = option;
            if (!string.IsNullOrEmpty(arg))
            {
                ParentFormHandle = (IntPtr)Int32.Parse(arg);
            }
            InitializeComponent();
            InitCtrls();
        }

        private void InitCtrls()
        {
            SetCustomStyles();
            SetMenuItemsEnabled(_isPlayerOn);
            InitVideoSourcePlayer();
            InitPictureBoxGif();
            if (ParentFormHandle != IntPtr.Zero)
            {
                this.Location = new System.Drawing.Point(0, 0);
            }
            else
            {
                int x = 0;
                int y = 0;
                int sw = Screen.PrimaryScreen.Bounds.Width;
                if (sw > this.Width)
                {
                    x = (sw - this.Width) / 2;
                }
                this.Location = new System.Drawing.Point(x, y);
            }
        }

        private void SetCustomStyles()
        {
            this.SetStyle(ControlStyles.UserPaint
              | ControlStyles.AllPaintingInWmPaint
              | ControlStyles.OptimizedDoubleBuffer
              | ControlStyles.ResizeRedraw,
              true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.Opaque, false);
            this.UpdateStyles();
        }

        private void InitVideoSourcePlayer()
        {
			System.Drawing.Size size = _option.VideoPlayerSize;
            this.Size = size;
            videoSourcePlayer1.Parent = panel1;
            videoSourcePlayer1.Size = new System.Drawing.Size(size.Width - 2, size.Height - 2);
            videoSourcePlayer1.Location = new System.Drawing.Point(0, 0);
            //videoSourcePlayer1.RotateFlipValue = _camera.Option.RotateFlipValue;
        }

        private void UpdateControlEnable(Control ctrl, bool enable)
        {
            ctrl.BeginInvoke(new Action(() =>
            {
                ctrl.Enabled = enable;
            }));
        }

        private void OnError(object sender, string strMessage)
        {
            //takePhotoToolStripMenuItem.Enabled = true;
            Log.WriteAsync($"Camera error: {strMessage}");
            //MessageBox.Show(strMessage);
            SendCommand(CustomWindowsMessage.MSG_CAP_PHOTO_Fail, strMessage);
        }

        //相机支持的快门设置列表
        CameraValue[] TvSettingsList = null;
        private void FormCapturer_Load(object sender, EventArgs e)
        {
            try
            {   
                if (InitCamera())
                {
                    TvSettingsList = this._camera.MainCamera.GetSettingsList(PropertyID.Tv);
                    OnAppStartupFinished();
                }
                else
                {
                    OnAppStartupFinished(0, "连接单反相机失败。");
					if (ParentFormHandle == IntPtr.Zero)
					{
						MessageBox.Show("父窗体句柄为空");
					}
				}
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
                OnAppStartupFinished(0, ex.Message);
            }
        }

        public void OnPhotoTaken(Bitmap source)
        {
            if (this.InvokeRequired)
            {
                Action<Bitmap> outdelegate = new Action<Bitmap>(OnPhotoTaken);
                this.BeginInvoke(outdelegate, new object[] { source });
                return;
            }
            SendCommand(CustomWindowsMessage.MSG_CAP_PHOTO_OK);
            takePhotoToolStripMenuItem.Enabled = true;
            // 进入拍照显示状态，暂停视频流更新和人脸检测
            if (_displayEffects)
            {
                Bitmap bitmap = ComLib.ComFun.BitmapFunc.Clone(source);
                videoSourcePlayer1.Visible = false;          
                ShowPhotoTakenEffects(bitmap); 
                videoSourcePlayer1.Visible = true;
                bitmap.Dispose();
                bitmap = null;
            }         
        }

        public void OnShottingCompleted()
        {
            videoSourcePlayer1.Visible = false;
        }

        private void StartCapturer()
        {
            //加载默认参数
            DslrProperties properties = new DslrProperties();
            properties.LoadPopertiesFromIni();
            //SetDefaultSetting(properties);

            this._camera.StartLiveView();
            _isPlayerOn = true;
            SetMenuItemsEnabled(_isPlayerOn);
            Log.WriteAsync("镜头已打开，播放器已启动...");
            SendCommand(CustomWindowsMessage.MSG_CAP_START_OK);
        }

        private void StopCapturer()
        {
            if (!_isPlayerOn)
            {
                return;
            }
            _isPlayerOn = false;
            SetMenuItemsEnabled(_isPlayerOn);
            Log.WriteAsync("镜头已经关闭，播放器已经停止运行...");
            SendCommand(CustomWindowsMessage.MSG_CAP_STOP_OK);
            this._camera.StopLiveView();
        }

        public static Bitmap BytesToBitmap(byte[] Bytes)
        {
            MemoryStream stream = null;
            try
            {
                stream = new MemoryStream(Bytes);
                return new Bitmap(new Bitmap(stream));
            }
            catch (ArgumentNullException ex)
            {
                throw ex;
            }
            catch (ArgumentException ex)
            {
                throw ex;
            }
            finally
            {
                stream.Close(); 
                stream.Dispose();
                stream = null;
            }
        }

        //private void TakeImageFormShareMemory()
        //{
        //    if (this.InvokeRequired)
        //    {
        //        Action handler = new Action(TakeImageFormShareMemory);
        //        this.BeginInvoke(handler, new object[] { });
        //        return;
        //    }
        //    Bitmap bmp = BytesToBitmap(Data);
        //    OnPhotoTaken(bmp);
        //    if (_showTakenPhoto)
        //    {
        //        FormPhotoPreviewing form = new FormPhotoPreviewing(bmp);
        //        form.ShowDialog();
        //    }
        //    bmp.Dispose();
        //    bmp = null;
        //}

        //private void OnPhotoDataWrittenInShareMemory(object sender, EventArgs e)
        //{
        //    Mutex mutex = Mutex.OpenExisting(mutexName);
        //    if (!mutex.WaitOne(1000))
        //    {
        //        MessageBox.Show("等待处理共享数据超时!");
        //        return;
        //    }
        //    using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(shareName))
        //    {             
        //        using (MemoryMappedViewStream stream = mmf.CreateViewStream(0, 8)) //注意这里的偏移量
        //        {
        //            var reader = new BinaryReader(stream);
        //            nReadDataLength = reader.ReadInt64();
        //        }
        //        using (MemoryMappedViewStream stream = mmf.CreateViewStream(8, 0)) //注意这里的偏移量
        //        {
        //            var reader = new BinaryReader(stream);
        //            Data = new Byte[nReadDataLength];
        //            reader.Read(Data, 0, (int)nReadDataLength);
        //        }              
        //    }
        //    mutex.ReleaseMutex();
        //    TakeImageFormShareMemory();
        //}

        /// <summary>
        /// 执行拍照命令，激活拍照开关
        /// </summary>
        /// <param name="showing">指示是否显示拍照结果，默认否</param>
        /// <param name="displayEffect">指示是否显示拍照特效，默认否</param>
        private void TakePhoto(bool showing = false, bool displayEffect = false)
        {
            _showTakenPhoto = showing;
            _displayEffects = displayEffect;
            if (this._camera != null && this._camera.IsConnected)
            {
                this._camera.SimulateTrigger();
            }
            //if (_device != null)
            //{
            //    _device.NeedWriteToMemoryMappedFile = true;
            //}
        }

        public bool InitCamera()
        {
            if (!_camera.Connect(""))//不指定单反名
            {
                MessageBox.Show("照相机打开失败");
                return false;
            }
            CanonDSLRCamera.CreatMutex();
            this._camera.NewFrame += this.camera_NewFrame;
            this._camera.SnapshotFrame += this.snapshot_NewFrame;
            this._camera.Error += this.OnError;
            return true;
        }

        /// <summary>
        /// 为单反设置默认参数
        /// </summary>
        /// <param name="properties"></param>
        private void SetDefaultSetting(DslrProperties properties)
		{
            _camera.MainCamera.SetSetting(PropertyID.Tv, properties[PropertyID.Tv].Value);
            _camera.MainCamera.SetSetting(PropertyID.Av, properties[PropertyID.Av].Value);
            _camera.MainCamera.SetSetting(PropertyID.ISO, properties[PropertyID.ISO].Value);
            _camera.MainCamera.SetSetting(PropertyID.WhiteBalance, properties[PropertyID.WhiteBalance].Value);
            _camera.MainCamera.SetSetting(PropertyID.ImageQuality, properties[PropertyID.ImageQuality].Value);
            _camera.MainCamera.SetSetting(PropertyID.MeteringMode, properties[PropertyID.MeteringMode].Value);
            _camera.MainCamera.SetSetting(PropertyID.PictureStyle, properties[PropertyID.PictureStyle].Value);
            _camera.MainCamera.SetSetting(PropertyID.Evf_AFMode, properties[PropertyID.Evf_AFMode].Value);
        }

        private void camera_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            if (base.InvokeRequired)
            {
                this.VideoFrame = eventArgs.Frame;
                base.BeginInvoke(new NewFrameEventHandler(this.camera_NewFrame), sender, eventArgs);
            }
            else
            {
                try
                {
                    Image image = this.videoSourcePlayer1.Image;
                    Image videoFrame = this.VideoFrame;
                    if (videoFrame != null)
                    {
                        if (this._drawFocusRect)
                        {
                            this.DrawFocusInfo(videoFrame);
                        }
                        this.EvfDataSet = eventArgs.EvfDataSet;
                        if (this._drawZoomRect)
                        {
                            this.DrawZoomFrame(videoFrame);
                        }
                        videoFrame.RotateFlip(this._rotateLiveView);
                       
                        this.videoSourcePlayer1.Image = videoFrame;
                        if (image != null)
                        {
                            image.Dispose();
                        }
                        //this.labelPreview.Text = videoFrame.Width + "*" + videoFrame.Height;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }

        private void DrawCalibInfo(ref Image bmp, System.Drawing.Rectangle rect, int eyePos)
        {
            Bitmap bitmap = ComLib.ComFun.BitmapFunc.BmpClone(bmp as Bitmap);
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                graphics.DrawRectangle(this.penBlue, rect.X, rect.Y, rect.Width, rect.Height);
                int num = eyePos + rect.Y;
                graphics.DrawLine(this.penGreen, 0, num, bmp.Width, num);
            }
            bmp.Dispose();
            bmp = bitmap;
        }

        private void DrawZoomFrame(Image bmp)
        {
            using (Graphics graphics = Graphics.FromImage(bmp))
            {
                int width = bmp.Width;
                int height = bmp.Height;
                int width2 = this.EvfDataSet.ImageSize.Width;
                int height2 = this.EvfDataSet.ImageSize.Height;
                long num = this.EvfDataSet.ZoomRect.X;
                long num2 = this.EvfDataSet.ZoomRect.Y;
                float num3 = (float)num * (float)width / (float)width2;
                float num4 = (float)num2 * (float)height / (float)height2;
                float num5 = (float)this.EvfDataSet.ZoomRect.Width * (float)width / (float)width2;
                float num6 = (float)this.EvfDataSet.ZoomRect.Height * (float)height / (float)height2;
                graphics.DrawRectangle(this.penWhite, num3, num4, num5, num6);
                int x = (int)(num3 + num5 / 2f);
                int y = (int)(num4 + num6 / 2f);
                EOSDigital.SDK.Point point = new EOSDigital.SDK.Point(x, y);
                this.PointRotateFlip(ref point, this._rotateLiveView);
                //this.labelFocusPointLocation.Text = point.X + "," + point.Y;
            }
        }

        private void DrawFocusInfo(Image bmp)
        {
            FocusInfo focusInfo = this._evfDataSet.FocusInfo;
            if (focusInfo.PointNumber > 0 && focusInfo.PointNumber <= 32)
            {
                using (Graphics graphics = Graphics.FromImage(bmp))
                {
                    int width = bmp.Width;
                    int height = bmp.Height;
                    double num = (double)width / (double)focusInfo.ImageRectangle.Width;
                    double num2 = (double)height / (double)focusInfo.ImageRectangle.Height;
                    for (int i = 0; i < focusInfo.PointNumber; i++)
                    {
                        FocusPoint focusPoint = focusInfo.FocusPoints[i];
                        int x = (int)((double)focusPoint.Rectangle.X * num);
                        int y = (int)((double)focusPoint.Rectangle.Y * num2);
                        int width2 = (int)((double)focusPoint.Rectangle.Width * num);
                        int height2 = (int)((double)focusPoint.Rectangle.Height * num2);
                        System.Drawing.Rectangle rect = new System.Drawing.Rectangle(x, y, width2, height2);
                        if (focusPoint.Valid == 1)
                        {
                            Pen pen = ((focusPoint.JustFocus & 0xF) != 1) ? (((focusPoint.JustFocus & 0xF) == 2) ? this.penRed : (((focusPoint.JustFocus & 0xF) != 4) ? this.penWhite : this.penBlue)) : this.penGreen;
                            if (focusPoint.Selected != 1)
                            {
                                pen = this.penGray;
                            }
                            graphics.DrawRectangle(pen, rect);
                            if (focusInfo.PointNumber == 1)
                            {
                                int x2 = rect.X + rect.Width / 2;
                                int y2 = rect.Y + rect.Height / 2;
                                EOSDigital.SDK.Point point = new EOSDigital.SDK.Point(x2, y2);
                                this.PointRotateFlip(ref point, this._rotateLiveView);
                                //this.labelFocusPointLocation.Text = point.X + "," + point.Y;
                            }
                        }
                    }
                }
            }
        }

        private void snapshot_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new NewFrameEventHandler(this.snapshot_NewFrame), sender, eventArgs);
                return;
            }
            else
            {
                try
                {                           
                    OnPhotoTaken(eventArgs.Frame);
                    if (_showTakenPhoto)
                    {
                        Bitmap bitmap = ComLib.ComFun.BitmapFunc.Clone(eventArgs.Frame);
                        FormPhotoPreviewing form = new FormPhotoPreviewing(bitmap);
                        form.ShowDialog();
                        bitmap.Dispose();
                        bitmap = null;
                    }                
                }
                catch (Exception ex)
                {
                    Log.WriteException(ex.ToString());
                }
            }
        }

        private void PointRotateFlip(ref EOSDigital.SDK.Point p, RotateFlipType rotate)
        {
            switch (rotate)
            {
                case RotateFlipType.RotateNoneFlipNone:
                    break;
                case RotateFlipType.Rotate90FlipNone:
                    this.PointRotate(ref p, 90);
                    break;
                case RotateFlipType.Rotate180FlipNone:
                    this.PointRotate(ref p, 180);
                    break;
                case RotateFlipType.Rotate270FlipNone:
                    this.PointRotate(ref p, 270);
                    break;
                case RotateFlipType.RotateNoneFlipX:
                    this.PointFlipX(ref p);
                    break;
                case RotateFlipType.Rotate90FlipX:
                    this.PointFlipX(ref p);
                    this.PointRotate(ref p, 90);
                    break;
                case RotateFlipType.Rotate180FlipX:
                    this.PointFlipX(ref p);
                    this.PointRotate(ref p, 180);
                    break;
                case RotateFlipType.Rotate270FlipX:
                    this.PointFlipX(ref p);
                    this.PointRotate(ref p, 270);
                    break;
            }
        }

        private void PointRotate(ref EOSDigital.SDK.Point p1, int angle)
        {
            double num = (double)angle * 3.1415926535897931 / 180.0;
            double a = (double)p1.X * Math.Cos(num) + (double)p1.Y * Math.Sin(num);
            double a2 = (double)(-p1.X) * Math.Sin(num) + (double)p1.Y * Math.Cos(num);
            p1 = new EOSDigital.SDK.Point((int)Math.Round(a), (int)Math.Round(a2));
        }

        private void PointFlipX(ref EOSDigital.SDK.Point p)
        {
            p.X = -p.X;
        }

        private void PointFlipY(ref EOSDigital.SDK.Point p)
        {
            p.Y = -p.Y;
        }

        private void OnPlayerAborted(object sender, string reason)
        {
            if (this.InvokeRequired)
            {
                VideoSourcePlayer.PlayingAbortedEventHandler outdelegate
                    = new VideoSourcePlayer.PlayingAbortedEventHandler(OnPlayerAborted);
                this.BeginInvoke(outdelegate, new object[] { sender, reason });
                return;
            }
            Log.WriteAsync(string.Format("检测到镜头发生了错误, 原因:{0}", reason));
            SendCommand(CustomWindowsMessage.MSG_CAP_ERROR, reason);
        }

        private void SetMenuItemsEnabled(bool playing)
        {
            startViewToolStripMenuItem.Enabled = !playing;
            stopViewToolStripMenuItem.Enabled = playing;
            takePhotoToolStripMenuItem.Enabled = playing;
            cameraSettingToolStripMenuItem.Enabled = playing;
            takingOptionToolStripMenuItem.Enabled = !playing;
            exitToolStripMenuItem.Enabled = !playing;
            //aboutToolStripMenuItem.Enabled = true;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
          
        }
  
        private void InitPictureBoxGif()
        {
            pictureBoxGif.Size = panel1.Size;
            pictureBoxGif.Parent = panel1;
            pictureBoxGif.Location = new System.Drawing.Point(0, 0);
            pictureBoxGif.Visible = false;
        }

        private void CloseAllOtherForm()
        {
            if (AutoMetroMessageBox.isOnShowing)
            {
                AutoMetroMessageBox.Close(false);
            }
            if (formConfig != null && !formConfig.IsDisposed)
            {
                formConfig.Close();
                formConfig.Dispose();
                formConfig = null;
            }
        }

        public void CloseAutoMessageBox()
        {
            if (AutoMetroMessageBox.isOnShowing)
            {
                AutoMetroMessageBox.Close(false);
            }
        }

        private void OpenProcessSettings()
        {
            if ((formConfig != null
                && !formConfig.IsDisposed)
                || _camera == null)
            {
                return;
            }
            try
            {
                if (formConfig == null)
                {
					//参数设置
					formConfig = new FormDSLRCameraSetting(_camera);
					formConfig.ShowDialog();
					formConfig.Dispose();
					formConfig = null;
				}
            }
            catch (Exception ex)
            {
                Log.WriteException("捕获异常:" + ex.ToString());
            }
        }

        /// <summary>
        /// 显示拍照特效
        /// </summary>
        /// <param name="MyBitmap"></param>
        private void ShowPhotoTakenEffects(Bitmap img)
        {
            Bitmap transImage = AForge.Imaging.Image.Clone(img);
            transImage.RotateFlip(RotateFlipType.RotateNoneFlipX);
            pictureBoxGif.Visible = true;
            try
            {
                // 播放特效声音
                _player.Play();
                // 显示图形特效
                // 变黑再变亮显示图像
                using (Graphics g = this.pictureBoxGif.CreateGraphics())
                {
                    g.Clear(Color.Black);
                    int width = transImage.Width;
                    int height = transImage.Height;
                    int w =  _option.VideoPlayerSize.Width;
                    int h = _option.VideoPlayerSize.Height;
                    int x = (pictureBoxGif.Width - w) / 2;
                    int y = (pictureBoxGif.Height - h) / 2;
					System.Drawing.Rectangle showRec = new System.Drawing.Rectangle(x, y, w, h);
                    ImageAttributes attributes = new ImageAttributes();
                    ColorMatrix matrix = new ColorMatrix();
                    //创建淡出颜色矩阵
                    matrix.Matrix00 = (float)0.0;
                    matrix.Matrix01 = (float)0.0;
                    matrix.Matrix02 = (float)0.0;
                    matrix.Matrix03 = (float)0.0;
                    matrix.Matrix04 = (float)0.0;
                    matrix.Matrix10 = (float)0.0;
                    matrix.Matrix11 = (float)0.0;
                    matrix.Matrix12 = (float)0.0;
                    matrix.Matrix13 = (float)0.0;
                    matrix.Matrix14 = (float)0.0;
                    matrix.Matrix20 = (float)0.0;
                    matrix.Matrix21 = (float)0.0;
                    matrix.Matrix22 = (float)0.0;
                    matrix.Matrix23 = (float)0.0;
                    matrix.Matrix24 = (float)0.0;
                    matrix.Matrix30 = (float)0.0;
                    matrix.Matrix31 = (float)0.0;
                    matrix.Matrix32 = (float)0.0;
                    matrix.Matrix33 = (float)0.0;
                    matrix.Matrix34 = (float)0.0;
                    matrix.Matrix40 = (float)0.0;
                    matrix.Matrix41 = (float)0.0;
                    matrix.Matrix42 = (float)0.0;
                    matrix.Matrix43 = (float)0.0;
                    matrix.Matrix44 = (float)0.0;
                    matrix.Matrix33 = (float)1.0;
                    matrix.Matrix44 = (float)1.0;
                    //从1到0进行修改色彩变换矩阵主对角线上的数值
                    //依次减少每种色彩分量                 
                    Single count = (float)1.0;
                    while (count > 0.0)
                    {
                        matrix.Matrix00 = (float)count;
                        matrix.Matrix11 = (float)count;
                        matrix.Matrix22 = (float)count;
                        matrix.Matrix33 = (float)count;
                        attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
                        g.DrawImage(transImage, showRec, 0, 0, width, height, GraphicsUnit.Pixel, attributes);
                        System.Threading.Thread.Sleep(4);
                        count = (float)(count - 0.25);
                    }
                    //从0到1进行修改色彩变换矩阵主对角线上的数值
                    //使三种基准色的饱和度渐增
                    g.Clear(Color.Black);
                    System.Threading.Thread.Sleep(100);
                    count = (float)0.0;
                    while (count < 1.0)
                    {
                        matrix.Matrix00 = count;
                        matrix.Matrix11 = count;
                        matrix.Matrix22 = count;
                        matrix.Matrix33 = count;
                        attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
                        g.DrawImage(transImage, showRec, 0, 0, width, height, GraphicsUnit.Pixel, attributes);
                        System.Threading.Thread.Sleep(2);
                        count = (float)(count + 0.5);
                    }
                }
                transImage.Dispose();
                transImage = null;
                pictureBoxGif.Visible = false;
            }
            catch (Exception ex)
            {
                Log.WriteException("捕获异常:" + ex.ToString());
            }
        }

        /// <summary>
        /// 连续点击激活次数统计
        /// </summary>
        private int active_click_count = 0;

        private Stopwatch sw_click = new Stopwatch();

        private void OnEnterCamSettingSection()
        {
            // 工作页面不允许呼出菜单
            if ((formConfig != null && !formConfig.IsDisposed) 
                || _camera == null
                || !_isPlayerOn)
            {
                return;
            }
            if (sw_click.IsRunning)
            {
                if (sw_click.ElapsedMilliseconds > 2000)
                {
                    sw_click.Reset();
                    active_click_count = 0;
                }
                else
                {
                    active_click_count++;
                }
                if (active_click_count == 3)
                {
                    sw_click.Reset();
                    active_click_count = 0;
                    OpenProcessSettings();
                }
            }
            else
            {
                sw_click.Restart();
            }
        }

        private void videoSourcePlayer1_Click(object sender, EventArgs e)
        {
            OnEnterCamSettingSection();
        }

        private void pictureBoxGif_Click(object sender, EventArgs e)
        {
            OnEnterCamSettingSection();
        }

        /// <summary>
        /// 处理来自其他进程发来的消息
        /// </summary>
        /// <param name="m"></param>
        private void OnCustomMsgReceived(System.Windows.Forms.Message m)
        {
            try
            {
                COPYDATASTRUCT cdStruct = new COPYDATASTRUCT();
                Type mytype = cdStruct.GetType();
                cdStruct = (COPYDATASTRUCT)m.GetLParam(mytype);
                ControllerHandle = cdStruct.dwData;
                int id = (int)m.WParam;
                switch (id)
                {
                    case CustomWindowsMessage.MSG_CAP_SETTING:
                        {
                            Log.WriteAsync("收到消息，打开参数设置.");
                            OpenProcessSettings();
                        }
                        break;
                    case CustomWindowsMessage.MSG_CAP_DO:
                        {
                            Log.WriteAsync("收到消息，执行拍照.");
                            TakePhoto();
                        }
                        break;
                    case CustomWindowsMessage.MSG_CAP_DOFORMAL:
                        {
                            Log.WriteAsync("收到消息，执行正式拍照.");
                            TakePhoto(false, false);
                        }
                        break;
                    case CustomWindowsMessage.MSG_CAP_START:
                        {
                            Log.WriteAsync("收到消息，开始启动镜头预览.");
                            StartCapturer();
                        }
                        break;
                    case CustomWindowsMessage.MSG_CAP_STOP:
                        {
                            Log.WriteAsync("收到消息，停止镜头预览.");
                            StopCapturer();
                        }
                        break;
                    case CustomWindowsMessage.MSG_CAP_SETTING_ADD_SHUTTER_TIME:
						{
                            Log.WriteAsync("增加相机快门时间");
                            AddShutterTime();
                        }
                        break;
                    case CustomWindowsMessage.MSG_CAP_SETTING_DEC_SHUTTER_TIME:
                        {
                            Log.WriteAsync("减少相机快门时间");
                            DesShutterTime();
                        }
                        break;
                    default:
                        break;
                }
            }
            catch (Exception e)
            {
                Log.WriteException(e.ToString());
            }           
        }

		private int GetCurTvSettingIndex()
		{
            int value = _camera.MainCamera.GetInt32Setting(PropertyID.Tv, 0);           
            for(int i = 0; i < TvSettingsList.Length; i++)
			{
				if (TvSettingsList[i].IntValue == value)
				{
                    return i;
				}
			}
            return 0;
        }

        private void DesShutterTime()
		{
            int index = GetCurTvSettingIndex();
			if (index == TvSettingsList.Length - 1)
			{
                return;  //已经最小了，不能再减了
			}
            _camera.MainCamera.SetSetting(PropertyID.Tv, TvSettingsList[index+1].IntValue);
        }

        private void AddShutterTime()
        {
            int index = GetCurTvSettingIndex();
            if (index == 1)
            {
                return;  //已经最大了，不能再加了
            }

            _camera.MainCamera.SetSetting(PropertyID.Tv, TvSettingsList[index - 1].IntValue);
        }

        /// <summary>
        /// 通知当前模块回到应用程序主页
        /// </summary>
        private void SendCommand(int command, string message = "Command")
        {
            if(ControllerHandle != IntPtr.Zero)
            {
                int uMsg = WindowsMessage.WM_COPYDATA;
                int wParam = command;
                string strMsgText = message;
                int nLen = Encoding.Unicode.GetBytes(strMsgText).Length;
                COPYDATASTRUCT dataStr = new COPYDATASTRUCT();
                dataStr.dwData = (IntPtr)uMsg;
                dataStr.cbData = nLen;
                dataStr.lpData = strMsgText;
                WindowsAPI.SendMessage(ControllerHandle, uMsg, wParam, ref dataStr);
            }        
        }    

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case WindowsMessage.WM_COPYDATA:
                    OnCustomMsgReceived(m);
                    break;
                case WindowsMessage.WM_CLOSE:
                    OnClosing();
                    break;
                default:
                    break;
            }
            base.WndProc(ref m);
        }

        private void 启动预览ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Log.WriteAsync("收到右键启动预览消息，开始启动镜头预览.");
            StartCapturer();
        }

        private void stopViewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Log.WriteAsync("收到右键消息，停止镜头预览.");
            StopCapturer();
        }

        private void takePhotoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            takePhotoToolStripMenuItem.Enabled = false;
            Log.WriteAsync("收到右键消息，执行拍照.");
            TakePhoto(true, true);
        }

        private void cameraSettingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Log.WriteAsync("收到右键消息，打开镜头参数设置.");
            OpenProcessSettings();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormAbout form = new FormAbout();
            form.ShowDialog();
        }

        private void takingOptionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Log.WriteAsync("打开了拍照和预览选项设置");
            FormConfig form = new FormConfig();
            if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                AutoMetroMessageBox.Show(this, 
                    "参数设置成功!", 
                    "温馨提示",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information,
                    6);
                InitVideoSourcePlayer();
                //_camera.LoadConfig();
            }
        }

        private void OnClosing()
        {
            StopCapturer();
            _camera.Disconnect();
            Log.Exit();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// 通知主窗体该进程启动已经完成
        /// </summary>
        protected void OnAppStartupFinished(int code = 1, string msg = "程序加载成功")
        {
            // 当父窗体为空时，不需要通知
            if (IntPtr.Zero == ParentFormHandle || _bNotified)
            {
                Log.WriteAsync(string.Format("{0}获取父进程主窗口句柄为空，不启用进程监测.", AppName));
                return;
            }
            string sendMsg = string.Format("{0}#{1}#{2}", AppName, code, msg);
            Pipe t = new Pipe(2, sendMsg, "MainStartup");
            Task.Factory.StartNew(new Action(t.run));
            Log.WriteAsync("已经通知主窗体启动完成: " + AppName);
            _bNotified = true;
        }

        private void SetPlayerSize(System.Drawing.Size size)
        {               
            int iScreenWidth = Screen.PrimaryScreen.Bounds.Width;
            int iScreenHeight = Screen.PrimaryScreen.Bounds.Height;
            this.Size = size;
            if (size.Height <= iScreenHeight)
            {
                int x = (iScreenWidth - size.Width) / 2;
                int y = (iScreenHeight - size.Height) / 2;
                this.Location = new System.Drawing.Point(x, y);
            }
            else
            {
                this.Location = new System.Drawing.Point(0, 0);
            }
            videoSourcePlayer1.Parent = panel1;
            videoSourcePlayer1.Size = new System.Drawing.Size(size.Width - 2, size.Height - 2);
            videoSourcePlayer1.Location = new System.Drawing.Point(0, 0);
            InitPictureBoxGif();
        }

        private void toolStripMenuItemSize300_Click(object sender, EventArgs e)
        {
            SetPlayerSize(new System.Drawing.Size(250, 300));
        }

        private void toolStripMenuItemSize360_Click(object sender, EventArgs e)
        {
            SetPlayerSize(new System.Drawing.Size(300, 360));
        }

        private void toolStripMenuItemSize600_Click(object sender, EventArgs e)
        {
            SetPlayerSize(new System.Drawing.Size(500, 600));
        }

        private void toolStripMenuItemSize720_Click(object sender, EventArgs e)
        {
            SetPlayerSize(new System.Drawing.Size(600, 720));
        }

        private void toolStripMenuItemSize1080_Click(object sender, EventArgs e)
        {
            SetPlayerSize(new System.Drawing.Size(900, 1080));
        }

        private void toolStripMenuItemSize1440_Click(object sender, EventArgs e)
        {
            SetPlayerSize(new System.Drawing.Size(1200, 1440));
        }

        private void control_MouseDown(object sender, MouseEventArgs e)
        {
            if (ParentFormHandle != IntPtr.Zero)
            {
                return;
            }
            mouse_offset = new System.Drawing.Point(-e.X, -e.Y);
        }

        private System.Drawing.Point mouse_offset;

        private void videoSourcePlayer1_MouseMove(object sender, MouseEventArgs e)
        {
            if (ParentFormHandle != IntPtr.Zero)
            {
                return;
            }
            if (e.Button == MouseButtons.Left)
            {
                System.Drawing.Point mousePos = Control.MousePosition;
                mousePos.Offset(mouse_offset.X, mouse_offset.Y);
                Location = mousePos;
            }
        }

    }
}
